package libra.predicate.custom._2;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

/**
 * 自定义Predicate断言，测试不使用静态内部类Config的方式
 * @author libra
 */
@Component
public class OutterSelfPredicateRoutePredicateFactory extends AbstractRoutePredicateFactory<OutterSelfPredicateConfig> {
	// 构造函数需要将自身的静态内部Config类进行传入
	public OutterSelfPredicateRoutePredicateFactory() {
		super(OutterSelfPredicateConfig.class);
	}
	
	@Override
	public Predicate<ServerWebExchange> apply(OutterSelfPredicateConfig config) {
		// 断言判定的方法实现，true->匹配成功；false->匹配失败；
		return new GatewayPredicate() {
			@Override
			public boolean test(ServerWebExchange serverWebExchange) {
				// 通过该方法获取当次这次的Request请求对象
				ServerHttpRequest request = serverWebExchange.getRequest();
				// 判断请求方式，自定义实现
				if( !config.getMethod().equalsIgnoreCase( request.getMethodValue() ) )
					return false;
				// 判断请求Path，采用PathRoutePredicateFactory提供的默认实现
				Predicate<ServerWebExchange> pathPredicate = 
						new PathRoutePredicateFactory()
							.apply( new PathRoutePredicateFactory.Config().setPatterns(List.of(config.getPath())) );
				/*
				 * !!! 当且仅当同时满足以下两个条件时，才会映射放行请求
				 * 条件1：请求方式必须为yml配置method的指定请求方式
				 * 条件2：请求GATEWAY的url路径必须与yml配置的path一致
				 */
				return pathPredicate.test(serverWebExchange);
			}
		};
	}
	
	/**
	 * 通过该方法向Config类进行“值”设置
	 * 传入的值即为Config中的属性名，通过查找Config中的set方法进行设置“值”
	 * TIPS:
	 * 	如果yml配置中采用的是predicates.name、predicates.args.属性a/b/c...，的方式配置，shortcutFieldOrder()方法可以不要。
	 */
	@Override
	public List<String> shortcutFieldOrder() {
		return Arrays.asList("method","path");
	}
}
